/**
* File Name: server.c
* Auther: Jichang
* Environment: Fedora 7 server
* multi process concurrency
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<pthread.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<strings.h>
#include<ctype.h>
#include"wrap.h"

#define SRV_PORT 9999

void catch_child(int signum) {
	while(waitpid(0, NULL, WNOHANG) > 0);
	return ;
}

void sys_err(const char *str) {
	perror(str);
	exit(1);
}

int main(int argc, char *argv[])
{
	int lfd, cfd;
	int ret = 0, i;
	pid_t pid;
	struct sockaddr_in server_addr, client_addr;
	socklen_t client_addr_len;
	char buf[BUFSIZ];

	//memset(&server_addr, 0, sizeof(server_addr)); // clean 0 addr_struct.
	bzero(&server_addr, sizeof(server_addr));
	// init.
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SRV_PORT);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	lfd = Socket(AF_INET, SOCK_STREAM, 0);
	Bind(lfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	Listen(lfd, 128);

	client_addr_len = sizeof(client_addr);
	while(1) {
		cfd = Accept(lfd, (struct sockaddr *)&client_addr, &client_addr_len);
		// create child_proc
		pid = fork();
		if(pid < 0) {
			sys_err("fork error");
		} else if(pid == 0) {
			close(lfd);
			break; // child_proc
		} else {
			// recycle
			struct sigaction act;
			act.sa_handler = catch_child; // signal catch function.
			sigemptyset(&act.sa_mask);
			act.sa_flags = 0;
			ret = sigaction(SIGCHLD, &act, NULL);
			if(ret != 0) {
				sys_err("sigaction error");
			}
			// parent proc
			close(cfd);
			continue;
		}
	}
	// form up break.
	if(pid == 0) {
		while(1) {	
			ret = Read(cfd, buf, sizeof(buf));
			if(ret == 0) {
				// client close
				close(cfd);
				exit(1);
			}
			for(i = 0; i < ret; i++) {
				buf[i] = toupper(buf[i]);
			}
			write(cfd, buf, ret);
			write(STDOUT_FILENO, buf, ret); // out screen
			close(0);
		}
	}

	
	return 0;
}

